package com.ofek.base.db;

import java.lang.reflect.Field;
import java.util.HashMap;



public class Table<Item> {

	protected SQLDatabase database;
	protected HashMap<String, Column> columns = new HashMap<String, Column>();
	private String tableName;
	protected Class<Item> clazz;

	public Table(final SQLDatabase db, final Class<Item> clazz) {
		database = db;
		this.clazz = clazz;
		if (!clazz.isAnnotationPresent(DataTypeClass.class))
			throw new IllegalArgumentException(clazz
					+ " is not a DataTypeClass!");
		database.execSQL(init(clazz));

	}

	private String init(final Class<Item> clazz) {
		final StringBuilder columns = new StringBuilder();
		tableName = clazz.getSimpleName();
		final StringBuilder keys = new StringBuilder();
		int keysCount = 0;
		final Field[] fields = clazz.getDeclaredFields();
		for (final Field f : fields)
			if (f.isAnnotationPresent(DataField.class)) {
				final Column column = new Column(f);
				if (column.isKey())
					keysCount++;
			}
		if (keysCount > 1) {
			for (final Field f : fields)
				if (f.isAnnotationPresent(DataField.class)) {
					final Column column = new Column(f);
					columns.append(column);
					columns.append(',');
					if (column.isKey()) {
						keys.append(column.getName());
						keys.append(',');
					}
					this.columns.put(f.getName(), column);
				}
			keys.deleteCharAt(keys.length() - 1);
		} else {
			for (final Field f : fields)
				if (f.isAnnotationPresent(DataField.class)) {
					final Column column = new Column(f);
					columns.append(column);
					if (column.isKey())
						columns.append(" PRIMARY KEY");
					columns.append(',');
					this.columns.put(f.getName(), column);
				}
		}
		columns.deleteCharAt(columns.length() - 1);
		return getCreateString(tableName, columns.toString(), keys.toString());
	}

	protected static String getCreateString(final String tableName,
			final String columnsAndTypes, final String keys) {
		final String inside = columnsAndTypes
				+ (keys.length() > 0 ? ",primary key ( " + keys + " )" : "");
		return "create table if not exists " + tableName + " ( " + inside
				+ " ); ";
	}

//	public long add(final Item a) {
//		return database.insertOrThrow(tableName, null, itemToValues(a,false));
//	}
//	public long replace(final Item a) {
//		return database.replaceOrThrow(tableName, null, itemToValues(a,true));
//	}
//	private ContentValues itemToValues(final Item a,final boolean replace) {
//		final ContentValues contentValues = new ContentValues();
//		for (final Column c : columns.values()) {
//			if (c.isKey() && c.isAutoIncrement() && !replace)
//				continue;
//			final String type = c.getType();
//			if (type.equals("long"))
//				contentValues.put(c.getName(), (Long) c.get(a));
//			else if (type.equals("int"))
//				contentValues.put(c.getName(), (Integer) c.get(a));
//			else if (type.equals("boolean"))
//				contentValues.put(c.getName(), (Boolean) c.get(a) ? 1 : 0);
//			else if (type.equals("text"))
//				contentValues.put(c.getName(), (String) c.get(a));
//			else if (type.equals("real"))
//				contentValues.put(c.getName(), (Float) c.get(a));
//		}
//		
//		return contentValues;
//	}
//
//	public void addAll(final ArrayList<Item> items) {
//		for (final Item i : items)
//			add(i);
//	}
//
//	public void remove(final Item i) {
//		database.delete(tableName, getEqualityWhereClause(i), null);
//	}
//
//	public ArrayList<Item> getAll() {
//		ArrayList<Item> items;
//		final Cursor c = database.rawQuery("SELECT * FROM " + tableName, null);
//		items = getAll(c);
//		c.close();
//		return items;
//	}
//
//	protected ArrayList<Item> getAll(final Cursor c) {
//		final ArrayList<Item> items = new ArrayList<Item>();
//		if (c.moveToFirst()) {
//			do {
//				try {
//					items.add(getItemFromCursor(c, clazz.newInstance()));
//				} catch (final Exception e) {
//					e.printStackTrace();
//				}
//			} while (c.moveToNext());
//		}
//		return items;
//	}
//
//	public Item getItemFromCursor(final Cursor c, final Item item) {
//		for (final Column col : columns.values()) {
//			final String type = col.getType();
//			if (type.equals("long"))
//				col.set(item, c.getLong(c.getColumnIndexOrThrow(col.getName())));
//			else if (type.equals("int"))
//				col.set(item, c.getInt(c.getColumnIndexOrThrow(col.getName())));
//			else if (type.equals("boolean"))
//				col.set(item,
//						c.getInt(c.getColumnIndexOrThrow(col.getName())) != 0);
//			else if (type.equals("text"))
//				col.set(item,
//						c.getString(c.getColumnIndexOrThrow(col.getName())));
//			else if (type.equals("real"))
//				col.set(item,
//						c.getFloat(c.getColumnIndexOrThrow(col.getName())));
//		}
//		return item;
//	}
//
//	public String getEqualityWhereClause(final Item i) {
//		final StringBuilder stringBuilder = new StringBuilder();
//		for (final Column c : columns.values()) {
//			if (c.isKey()) {
//				stringBuilder.append(c.getName());
//				stringBuilder.append('=');
//				stringBuilder.append("'" + c.get(i) + "'");
//				stringBuilder.append(" and ");
//			}
//		}
//		final int length = stringBuilder.length();
//		stringBuilder.delete(length - 4, length);
//		return stringBuilder.toString();
//	}
//
//	public boolean contains(final Item i) {
//		final String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE "
//				+ getEqualityWhereClause(i);
//		final SQLiteStatement statement = database.compileStatement(sql);
//		final long count = statement.simpleQueryForLong();
//		return count > 0;
//	}
//
//	public Item get(final Item itemWithSameID) {
//		Item item = null;
//		final Cursor c = database.query(tableName, null,
//				getEqualityWhereClause(itemWithSameID), null, null, null, null);
//		if (c.moveToFirst())
//			item = getItemFromCursor(c, itemWithSameID);
//		c.close();
//		return item;
//	}
//
//	public long size() {
//		final String sql = "SELECT COUNT(*) FROM " + tableName;
//		final SQLiteStatement statement = database.compileStatement(sql);
//		final long count = statement.simpleQueryForLong();
//		return count;
//	}
//
//	public void clear() {
//		database.delete(tableName, null, null);
//	}
//
//	public void update(final Item i) {
//		database.update(tableName, itemToValues(i,true), getEqualityWhereClause(i),null);
//
//	}
//
//	public String getTableName() {
//		return tableName;
//	}

}
